package com.ssm.spring.aop.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * Author  zxy
 * Date  2022/11/12 上午 9:50
 */
@Component
public class LoggerAspect {

    // 重用切入点表达式
    @Pointcut("execution(* com.ssm.spring.aop.xml.CalculatorImpl.*(..))")
    public void pointCut(){}

    public void beforeAdviceMethod(JoinPoint joinPoint){
        // JoinPoint：获取连接点所对应方法的信息
        // 获取签名信息
        Signature signature = joinPoint.getSignature();
        // 获取参数
        Object[] args = joinPoint.getArgs();

        System.out.println("LoggerAspect, 方法：" + signature.getName() +
                ",参数：" + Arrays.toString(args));
    }

    // 后置通知：在finally中执行
    public void afterAdviceMethod(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        System.out.println("LoggerAspect, 方法：" + signature.getName() + "执行完毕" );
    }

    // 返回通知：在返回值之后执行，returning属性值：获取方法结果
    public void afterReturningAdviceMethod(JoinPoint joinPoint, Object result){
        Signature signature = joinPoint.getSignature();
        System.out.println("LoggerAspect，方法：" + signature.getName() +
                "，结果：" + result);
    }

    // 异常通知，throwing获取异常
    public void afterThrowingAdviceMethod(JoinPoint joinPoint, Throwable ex){
        Signature signature = joinPoint.getSignature();
        System.out.println("LoggerAspect，方法：" + signature.getName() +
                "，异常：" + ex.toString());
    }

    // 必须返回（和目标对象返回值一致）
    public Object aroundAdviceMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        // 表示目标对象方法的执行
        try {
            System.out.println("环绕通知->前置通知");
            result = joinPoint.proceed();
            System.out.println("环绕通知->返回通知");
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("环绕通知->异常通知");
        } finally {
            System.out.println("环绕通知->后置通知");
        }
        return result;
    }

}
